promise 与 async

个人笔记整理,有误欢迎指正

作者 Mr.Woo 日期 2019-04-14
promise 与 async

promise 与 async

一、了解js的执行过程


js一门单线程的脚本语言,它执行代码一般从上往下逐行执行。如果过程中遇到异步操作,则将该操作先挂起到任务队列中,接着继续执行同步代码。待主线程中都执行完毕,询问任务队列中任务是否完成,未完成则逐个执行,直到最终任务队列所有执行完毕。

其实在任务队列中还会区分宏任务与微任务,正如上图。

二、promise

1
2
3
4
5
6
let a = new Promise(resolve,reject){
resolve(1)
}.then(function(res){
console.log(res)
}).catch(function(){
})

以上就是一个简单的promise对象。promise有以下几点特效:

  1. promise属于宏任务
  2. promise的构造函数是同步,而then里的是异步
  3. promise状态不可逆
  4. then或catch return出去的数值会被后面的then或者catch接受
  5. promise不管返回什么,都会被包装成promise对象,即使返回一个error
  6. then接收到的如果不是函数,会发生穿透
  7. promise对象resolve或者reject一个promise对象,前一个promise的状态会由后一个决定
例子一
1
2
3
4
5
6
7
8
9
10
setTimeout(function(){
console.log(1)
})
let a = new Promise(resolve,reject){
resolve()
}.then(function(res){
console.log(2)
}).catch(function(){
})

以下执行结果是先出2,再出1。setTimeout是微任务,而promise是宏任务,所以先执行了宏任务promise

例子二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
setTimeout(function(){
console.log(1)
})
let a = new Promise(resolve,reject){
resolve()
}.then(function(res){
setTimeout(function(){
console.log(2)
})
console.log(4)
}).catch(function(){
})
setTimeout(function(){
console.log(3)
})

以上执行结果为4、 1、3、2 。首先明确promise是宏任务,setTimeout是微任务。promise外面有两个setimeout是微任务,依次被挂起。而在promise中有console4,所以最先执行宏任务出来4。接着发现promise中有微任务setimeout,也被挂起,接着执行所有的微任务也就是1、3、2出来。

例子三
1
2
3
4
5
6
7
new Promise(function(res,rej){
console.log(1)
res(2)
}).then(function(res){
console.log(res)
})
console.log(3)

以上执行结果为1、3、2 。因为promise的构造函数是同步,而then里的是异步,所以promise的构造函数也在主线程上执行出来1,接着执行外面的3,最后才执行then里面的2

例子四
1
2
3
4
5
6
7
8
new Promise(function(res,rej){
res(2)
rej(3)
}).then(function(res){
console.log(res)
}).catch(function(err){
console.log(err)
})

如果在pomise中执行了res,是不会再执行catch函数的。虽然也执行了rej,但是内部会阻止其catch。因为promise的状态是不可逆的。

例子五
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let a = new Promise(function(res,rej){
setTimeout(function(){
res(b)
},1000)
})
let b = new Promise(function(res,rej){
setTimeout(function(){
rej(4)
},2000)
})
a.then(function(){
console.log(1)
}).catch(funtion(){
console.log(2)
})

以上执行执行的结果是2。根据promise对象resolve或者reject一个promise对象,前一个promise的状态会由后一个决定。第一个promise中执行res出第二个promise对象,所以最终取决于第二个promise执行的结果。假若第一个promise并不是执行出第二个promise对象,而是直接执行出个结果,最终结果又会不一样。

三、async

async函数特点:

  1. async函数会返回一个promise对象
  2. return错误会让返回的promise对象状态为reject
  3. 一般来说await后面的值是一个promise
  4. 内部如果await多个promise对象,则会等所有promise完成后再执行then
例子一
1
2
3
4
5
6
7
8
9
10
11
12
async function a(){
await b();
return 4
}
function b(){
console.log(3)
}
a().then(fucntion(res){
console.log(res)
})

以上执行的结果是3、4。在async中returen出是个promise对象,所以then的结果为4。

例子二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function a(){
await b();
return new error('error...')
}
function b(){
console.log(3)
}
a().then(fucntion(res){
console.log(res)
}).catch(function(err){
console.log(err)
})

以上执行结果会返回3、和一个错误。正是async函数的第二点特性。

例子三
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
async function a(){
let c = await b();
return c
}
function b(){
return new Promise(function(res,rej){
res(1)
})
}
a().then(fucntion(res){
console.log(res)
}).catch(function(err){
console.log(err)
})

以上执行结果为1。await后面必须跟一个promise对象,才会起到异步效果,不然await只会同步执行。

例子四
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
async function a(){
let c = await b();
let e = await d();
return c+e
}
function b(){
return new Promise(function(res,rej){
setTimeout(function(){
res(1)
},1000)
})
}
function d(){
return new Promise(function(res,rej){
setTimeout(function(){
res(2)
},5000)
})
}
a().then(fucntion(res){
console.log(res)
}).catch(function(err){
console.log(err)
})

以上结果会等待5秒输出一个3。正是async函数的第四点特性,会等待所有promise对象执行完成之后输出。像这种特性,正好可以解决如果有多个接口调用,可以利用这点,解决回调嵌套问题。